home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / sys / amiga / programmer / 4560 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.4 KB  |  109 lines

  1. Path: news.daimi.aau.dk!liborius
  2. From: liborius@daimi.aau.dk (Per Liboriussen)
  3. Newsgroups: comp.sys.amiga.programmer
  4. Subject: Re: 3 bugs in SAS/C v. 6.56
  5. Date: 1 Mar 1996 09:27:46 GMT
  6. Organization: DAIMI, Computer Science Dept. at Aarhus University
  7. Message-ID: <4h6fui$b1t@gjallar.daimi.aau.dk>
  8. References: <4gs3hk$7mp@gjallar.daimi.aau.dk> <4h0lvl$du2@newsserver.trl.OZ.AU>
  9. NNTP-Posting-Host: yen.daimi.aau.dk
  10.  
  11. Thus spake aduncan@rhea.trl.OZ.AU (Allan Duncan):
  12.  
  13. [ Original (slightly modified) code deleted]
  14.  
  15. >> Anyway, when a compiler evaluates a boolean expression such as ">", it
  16. >> must perform the usual integral promotions. This means that types narrower
  17. >> than int are promoted to int before the comparison. Even in your example
  18. >> above the compiler must take the (integer) constant 0x7fff, convert it to
  19.  
  20. >                    ^
  21. >                unsigned for ANSI
  22.  
  23. Not according to "The C Programming Language" by Kernighan and Ritchie
  24. (second edition). In Appendix A (the reference manual), section A2.5.1
  25. they say that an unsuffixed hexadecimal integer constant has the first
  26. possible of the following types: int, unsigned int, long int and unsigned
  27. long int.
  28.  
  29.  
  30. >Try this test programme (for a 32 bit int and 2's complement
  31. >arithmetic):
  32.  
  33. >#include        <stdio.h>
  34.  
  35. >#define K 0xFFFFFFFF
  36.  
  37. >main()
  38. >{
  39. >printf( "Int %d, long %d, short %d\n", sizeof( int ), sizeof( long int),
  40. >                                        sizeof( short int ) ) ;
  41. >if ( K > 0 ) printf( "ANSI C\n" ) ;
  42. >else printf( " trad C\n" ) ;
  43. >}
  44.  
  45. This is correct, but it is only because 0xFFFFFFFF is too big for an int
  46. that it becomes an unsigned int. In an implementation with 32-bit ints
  47. 0x7fff will always be an int.
  48.  
  49. On a slightly off-topic note I would like to comment on your use of "%d"
  50. to print the result of the sizeof operator. Since sizeof returns a "size_t"
  51. the safest way to print it is to use "%lu" and cast the value to (unsigned
  52. long), or at least in the example above cast it to int. (After all,
  53. sizeof(long int) is unlikely to be larger than INT_MAX ;-). )
  54. I am aware that it will (appear to) work on SAS/C and most other (non-msdos)
  55. systems and that you specified ints to be 32 bits, but you didn't mention
  56. the size of long ints ;-) (DEC Alpha, anyone?).
  57.  
  58.  
  59. >> unsigned short, and then immediately convert it back to int. Of course,
  60. >> the ISO C Standard does give permission for an implementation to carry out
  61. >> the comparison by any arcane magic it may wish, as long as a conforming
  62. >> program is not able to tell the difference. (The "as if" rule.)
  63. >> 
  64. >> (Note furthermore that even though a and b are both unsigned shorts, the
  65. >> type of the expression (a | b) is int!)
  66.  
  67. >a and b are promoted to int under ANSI, and hence a | b is int.  Trad. C
  68. >would have promoted a and b to u-int.
  69.  
  70. Correct again, but I must admit that I don't worry too much about K&R C
  71. these days. I find C's integer promotion rules plenty complicated without
  72. having to worry about mixing ANSI and K&R rules ;-).
  73. (Especially since promotion rules was probably one of the major areas of
  74. change in the ANSI standard (not counting prototypes, of course).)
  75.  
  76.  
  77. >Adding unsigned short c ;
  78. >and setting c = (a | b) before using c in the if changes the SAS
  79. >behaviour.  The implication is that SAS are doing a sign extension of a
  80. >and b on the int conversion in the if, but not in the assign...
  81. >now where is that dissassembler...
  82.  
  83. Oh, I can tell you about the generated code, if you really want to know...
  84.  
  85. In the original example showing the bug the relevant code looks like this:
  86.  
  87.        | 0010  3E3C FFFF                      MOVE.W      #FFFF,D7
  88.        | 0014  3C3C FFFF                      MOVE.W      #FFFF,D6
  89.        | 0018  3007                           MOVE.W      D7,D0
  90.        | 001A  8046                           OR.W        D6,D0
  91.        | 001C  0C40 7FFF                      CMPI.W      #7FFF,D0
  92.        | 0020  6F0C                           BLE.B       002E
  93.  
  94. The last instruction (BLE.B) is the culprit. It compares the values as
  95. words and then does a branch on overflow instead of carry (i.e., a signed
  96. compare of 16 bit values). When the expression is written as
  97.   if (a > 0x7fff) {
  98. it correctly generates a BLS.B instruction.
  99.  
  100. I can understand how it is possible for a bug like that to slip through.
  101. I find the second bug that I described in the original posting much more
  102. funny. (A conditional expression in a previous procedure caused the
  103. compiler to be confused about the constness of things.)
  104.  
  105.  
  106. --
  107. Per Liboriussen
  108. liborius@daimi.aau.dk
  109.